嗨~大家好我是Eric~ 音頻視覺化是一個很有趣的領域,不僅可以讓我們更直觀地感受音樂,還能提供一個極富吸引力的用戶體驗,在這篇文章中,我會展示如何使用 Web Audio API 和 Canvas API 來實現一個簡單但功能強大的音頻視覺化工具。
首先,我們需要一個 HTML 結構來放置我們的 canvas 和 audio 元素
<canvas id="canvas"></canvas>
<audio id="audio" src="./video.mp3" controls></audio>
我們先取得 audio 和 canvas 的 DOM
const audioEle = document.getElementById('audio');
const cvs = document.getElementById('canvas');
const ctx = cvs.getContext('2d');
接著定義一個函數 initCanvas 來初始化 canvas 的寬和高,在這裡特別考慮了裝置的像素比,以確保畫面在 Retina 顯示器上也能清晰呈現
const size = 800;
function initCanvas() {
cvs.width = size * window.devicePixelRatio;
cvs.height = size * window.devicePixelRatio;
cvs.style.width = cvs.style.height = size + 'px';
}
initCanvas();
接下來是定義核心的 draw 函數,它負責根據音頻數據來繪製視覺化圖形,在這裡我們嘗試畫一個地極圖
function draw(datas, maxValue) {
ctx.clearRect(0, 0, cvs.width, cvs.height);
const centerX = cvs.width / 2;
const centerY = cvs.height / 2;
const radianInterval = 2 * Math.PI / datas.length;
ctx.beginPath();
for (let i = 0; i < datas.length; i++) {
const value = datas[i];
const radian = i * radianInterval;
const length = (value / maxValue) * (cvs.width / 4);
const x = centerX + Math.cos(radian) * length;
const y = centerY + Math.sin(radian) * length;
if (i === 0) {
ctx.moveTo(x, y);
} else {
const prevX = centerX + Math.cos(radian - radianInterval) * (datas[i-1] / maxValue) * (cvs.width / 4);
const prevY = centerY + Math.sin(radian - radianInterval) * (datas[i-1] / maxValue) * (cvs.width / 4);
const cp1x = (prevX + x) / 2;
const cp1y = (prevY + y) / 2;
ctx.quadraticCurveTo(cp1x, cp1y, x, y);
}
}
ctx.strokeStyle = _getRandomColor();
ctx.lineWidth = 2;
ctx.stroke();
}
最後將 audio 元素設置了一個 onplay 事件,當音頻開始播放時,會初始化 AudioContext 和 AnalyserNode,並實時更新 canvas
update 函數負責在每一個畫面更新時調用 draw 函數,並傳遞當前的音頻數據。
let isInit = false;
let analyser, buffer;
audioEle.onplay = function () {
if (isInit) return;
const audioCtx = new AudioContext();
analyser = audioCtx.createAnalyser();
analyser.fftSize = 512;
buffer = new Uint8Array(analyser.frequencyBinCount);
const source = audioCtx.createMediaElementSource(audioEle);
source.connect(analyser);
analyser.connect(audioCtx.destination);
isInit = true;
update();
}
// 更新函數
function update() {
// 請求動畫幀
requestAnimationFrame(update);
// 檢查是否已初始化
if (!isInit) {
return
}
// 獲取頻率數據
analyser.getByteFrequencyData(buffer);
const offset = Math.floor(buffer.length * 2 / 3);
const datas = new Array(offset * 2);
for (let i = 0; i < offset; i++) {
datas[i] = datas[datas.length - i - 1] = buffer[i];
}
// 調用繪圖函數
draw(datas, 255);
}
以上就是如何使用 Web Audio API 和 Canvas API 來實現音頻視覺化的全過程,這次的分享就到這邊,我們明天見 ~